/*
 * Copyright (c) 2007-2008, Thomas Krause (tho.krause@gmail.com)
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of gidoo nor the names of its contributors may be used to
 *       endorse or promote products derived from this software without specific
 *       prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.gidoo.wickettools.xmledit.nodes;

import java.util.ArrayList;
import java.util.Hashtable;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.Model;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.gidoo.wickettools.WicketTools;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.Text;

/**
 * A class representing a default node for representing and manipulating a
 * XML-file in {@link XMLEditor}. <br>
 * It will be displayed as a HTML-block element.
 * @author <a href="tho.krause@gmail.com">Thomas Krause</a>
 */
public class BlockNode extends XMLContent 
{
  private String name;
  private Hashtable<String, String> attributes;
  private ArrayList<XMLContent> children;
  
  protected ListView lsvChildren;
  protected Label lblName;
  
  private ModalWindow window;
  
  /**
   * Constructor.
   * @param wicketId The wicket-id.
   * @param xmlElement The XML-node where the information for this block node comes from.
   * @param schemaTypeLoader A SchemaTypeLoader which is used to examine the XML schema.
   */
  public BlockNode(String wicketId, Element xmlElement, SchemaTypeLoader schemaTypeLoader)
  {
    super(wicketId);
    
    if(xmlElement == null)
    {
      throw(new IllegalArgumentException("invalid xmlNode"));
    }
    
    // members //
    attributes = new Hashtable<String, String>();
    for(Object c : xmlElement.getAttributes())
    {
      Attribute a = (Attribute) c;
      attributes.put(a.getName(), a.getValue());
      
    }
    
    children = new ArrayList<XMLContent>();
    for(Object o : xmlElement.getContent())
    {
      if(o instanceof Element)
      {
        Element e = (Element) o;
        children.add(new BlockNode("child", e, schemaTypeLoader));
      }
      else if(o instanceof Text)
      {
        Text c = (Text) o;
        children.add(new BlockTextNode("child", c));
      }
    }
    
    name = xmlElement.getName();
    
    // components //
    
    window = new ModalWindow("window");
    
    window.setContent(new AttributePanel(window.getContentId(), xmlElement,schemaTypeLoader));
    add(window);
    
    lsvChildren = new ChildrenListView("lsvChildren");
    add(lsvChildren);
    
    lblName = new Label("lblName", new Model(name));
    add(lblName);
    
    lblName.add(new AjaxEventBehavior("onclick") {

      @Override
      protected void onEvent(AjaxRequestTarget target)
      {
        window.show(target);
      }
    });
    
    
  }

  
  /** Updates the apperance of this component. Call this e.g. after you added
   * some new children. <br>
   * Will try to get an {@link org.apache.wicket.ajax.AjaxRequestTarget} and
   * will add itself to it but will not fail if this is not possible.
   */
  public void updateView()
  {
    lblName.setModelObject(name);
    lsvChildren.setList(children);
    
    if(hasBeenRendered())
    {
      WicketTools.addToAjaxRequestTarget(
        new Component[]{lblName,lsvChildren}, this);
    }
  }
  
  /** The attributes of this node: equals to it's XML-pendant.*/
  public Hashtable<String, String> getAttributes()
  {
    return attributes;
  }

  /** All children of this node: equals to it's XML-pendant. */
  public ArrayList<XMLContent> getChildren()
  {
    return children;
  }

  /** The name of this node: equals to it's XML-pendant. */
  public String getName()
  {
    return name;
  }
  
  /** Constructs a new XML Element from this node */
  public Element constructElement()
  {
    Element result = new Element(name);
    
    for(String key : attributes.keySet())
    {
      result.setAttribute(key, attributes.get(key));
    }
    
    for(XMLContent c : children)
    {
      if(c instanceof BlockNode)
      {
        BlockNode b = (BlockNode) c;
        Element child = b.constructElement();
        result.addContent(child);
      }
      else if(c instanceof BlockTextNode)
      {
        BlockTextNode t = (BlockTextNode) c;
        Text child = t.constructText();
        if(child != null)
        {
          result.addContent(child);
        }
      }
    }
    
    return result;
  }
  
  protected class ChildrenListView extends ListView
  {
    
    public ChildrenListView(String wicketId)
    {
      super(wicketId, children);
      this.setRenderBodyOnly(true);
    }
    
    @Override
    protected void populateItem(ListItem item)
    {
      int i = item.getIndex();
      children.get(i).setRenderBodyOnly(true);
      item.add(children.get(i));
      item.setRenderBodyOnly(true);
    }
    
  }
  
  
}
